#pragma once

#include <linux/bitops.h>
#include <linux/find.h>
#include <linux/string.h>
#include <linux/align.h>

#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))

#define bitmap_size(nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE)

unsigned int __bitmap_weight(const unsigned long *bitmap, unsigned int nbits);

static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, unsigned int nbits)
{
    unsigned int len = bitmap_size(nbits);

    if (small_const_nbits(nbits))
        *dst = *src;
    else
        memcpy(dst, src, len);
}

static inline unsigned int bitmap_weight(const unsigned long *src, unsigned int nbits)
{
    if (small_const_nbits(nbits))
        return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));

    return __bitmap_weight(src, nbits);
}
